package main

import (
	"fmt"
)

func main() {
	//// 直接写函数名是作为参数，函数名 + ()是函数调用
	//// 1. 匿名函数：没有函数名称，直接使用函数体 + ()完成调用
	//func() {
	//	fmt.Println("这是一个无参数无返回值的匿名函数!")
	//}()
	//res := func() string {
	//	str := "返回值"
	//	fmt.Println("这是一个无参数无返回值的匿名函数!", str)
	//	return str
	//}()
	//fmt.Printf("res = %s\n", res)
	//
	//func(a int) {
	//	fmt.Println("这是一个有参数无返回值的匿名函数!", a)
	//}(10)
	//res2 := func(a int) int {
	//	fmt.Println("这是一个有参数有返回值的匿名函数!", a)
	//	return a
	//}(20)
	//fmt.Printf("res2 = %d\n", res2)

	//// 2. 函数式编程：将一个函数/匿名函数作为参数
	//add := getResult(1, 2, add)	// 传入add函数
	//fmt.Println(add)
	//
	//sub := getResult(7, 2, sub)	// 传入sub函数
	//fmt.Println(sub)
	//
	//dev := getResult(10, 2, func(a, b int) int {	// 传入匿名函数
	//	if a == 0 {
	//		return 0
	//	}
	//	return a / b
	//})
	//fmt.Println(dev)

	//// 3.闭包：一个函数中返回了另一个函数，且另一个函数用到了外部函数的变量，
	//// 函数1调用结束后，此时变量不会消失
	//bao := biBao()
	//bao()
	//r := bao()
	//fmt.Println(r)
	//
	//bao2 := biBao()
	//bao2()
	//bao2()
	//r2 := bao2()
	//fmt.Println(r2)
	//r3 := bao()
	//fmt.Println(r3)

	// 4. defer语句：延时函数，类似java的finally，可用于关闭流/数据库连接
	// 多个defer将倒序执行，从下往上
	defer add(2, 3)
	defer sub(2, 3)
}

func biBao() func() int {
	i := 0
	return func() int {
		i++
		return i
	}
}

// 函数类型相同的，均可传入当作参数
func getResult(a, b int, c func(a, b int) int) int {
	// c是一个函数类型：func(int, int) int
	fmt.Printf("%T\n", c)
	return c(a, b)
}

func add(a, b int) int {
	fmt.Println("add")
	return a + b
}

func sub(a, b int) int {
	fmt.Println("sub")
	return a - b
}
